﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Cci;
using Microsoft.Cci.MutableCodeModel;

namespace Mutator
{
    class ConditionMutantGenerator : Microsoft.Cci.MutableCodeModel.MethodBodyCodeMutator
    {
        public List<Pair> list = new List<Pair>();
        public int counter = 0;
        Random rand = new Random();
        public ConditionMutantGenerator(IMetadataHost host)
            : base(host)
        {

        }
        public ConditionMutantGenerator(IMetadataHost host, ISourceLocationProvider/*?*/ sourceLocationProvider)
            : base(host, sourceLocationProvider)
        {

        }

        public override IExpression Visit(LessThanOrEqual lessThanOrEqual)
        {
            Console.WriteLine("++++++ lessThanOrEqual");

            BinaryOperation newOp1 = new LessThan();
            newOp1.LeftOperand = lessThanOrEqual.LeftOperand;
            newOp1.RightOperand = lessThanOrEqual.RightOperand;

            BinaryOperation newOp2 = new GreaterThan();
            newOp2.LeftOperand = lessThanOrEqual.LeftOperand;
            newOp2.RightOperand = lessThanOrEqual.RightOperand;

            BinaryOperation newOp3 = new GreaterThanOrEqual();
            newOp3.LeftOperand = lessThanOrEqual.LeftOperand;
            newOp3.RightOperand = lessThanOrEqual.RightOperand;

            BinaryOperation newOp4 = new Equality();
            newOp4.LeftOperand = lessThanOrEqual.LeftOperand;
            newOp4.RightOperand = lessThanOrEqual.RightOperand;

            BinaryOperation newOp5 = new NotEquality();
            newOp5.LeftOperand = lessThanOrEqual.LeftOperand;
            newOp5.RightOperand = lessThanOrEqual.RightOperand;


            list.Add(new Pair(lessThanOrEqual, newOp1));
            list.Add(new Pair(lessThanOrEqual, newOp2));
            list.Add(new Pair(lessThanOrEqual, newOp3));
            list.Add(new Pair(lessThanOrEqual, newOp4));
            list.Add(new Pair(lessThanOrEqual, newOp5));
            return this.Visit((BinaryOperation)lessThanOrEqual);
        }
        public override IExpression Visit(LessThan lessThan)
        {
            Console.WriteLine("++++++ lessThan");

            BinaryOperation newOp1 = new LessThanOrEqual();
            newOp1.LeftOperand = lessThan.LeftOperand;
            newOp1.RightOperand = lessThan.RightOperand;

            BinaryOperation newOp2 = new GreaterThan();
            newOp2.LeftOperand = lessThan.LeftOperand;
            newOp2.RightOperand = lessThan.RightOperand;

            BinaryOperation newOp3 = new GreaterThanOrEqual();
            newOp3.LeftOperand = lessThan.LeftOperand;
            newOp3.RightOperand = lessThan.RightOperand;

            BinaryOperation newOp4 = new Equality();
            newOp4.LeftOperand = lessThan.LeftOperand;
            newOp4.RightOperand = lessThan.RightOperand;

            BinaryOperation newOp5 = new NotEquality();
            newOp5.LeftOperand = lessThan.LeftOperand;
            newOp5.RightOperand = lessThan.RightOperand;


            list.Add(new Pair(lessThan, newOp1));
            list.Add(new Pair(lessThan, newOp2));
            list.Add(new Pair(lessThan, newOp3));
            list.Add(new Pair(lessThan, newOp4));
            list.Add(new Pair(lessThan, newOp5));
            return this.Visit((BinaryOperation)lessThan);
        }

         public override IExpression Visit(GreaterThanOrEqual greaterThanOrEqual)
         {
             Console.WriteLine("++++++ greaterThanOrEqual");

             BinaryOperation newOp1 = new LessThan();
             newOp1.LeftOperand = greaterThanOrEqual.LeftOperand;
             newOp1.RightOperand = greaterThanOrEqual.RightOperand;

             BinaryOperation newOp2 = new GreaterThan();
             newOp2.LeftOperand = greaterThanOrEqual.LeftOperand;
             newOp2.RightOperand = greaterThanOrEqual.RightOperand;

             BinaryOperation newOp3 = new LessThanOrEqual();
             newOp3.LeftOperand = greaterThanOrEqual.LeftOperand;
             newOp3.RightOperand = greaterThanOrEqual.RightOperand;

             BinaryOperation newOp4 = new Equality();
             newOp4.LeftOperand = greaterThanOrEqual.LeftOperand;
             newOp4.RightOperand = greaterThanOrEqual.RightOperand;

             BinaryOperation newOp5 = new NotEquality();
             newOp5.LeftOperand = greaterThanOrEqual.LeftOperand;
             newOp5.RightOperand = greaterThanOrEqual.RightOperand;


             list.Add(new Pair(greaterThanOrEqual, newOp1));
             list.Add(new Pair(greaterThanOrEqual, newOp2));
             list.Add(new Pair(greaterThanOrEqual, newOp3));
             list.Add(new Pair(greaterThanOrEqual, newOp4));
             list.Add(new Pair(greaterThanOrEqual, newOp5));
             return this.Visit((BinaryOperation)greaterThanOrEqual);
         }
         public override IExpression Visit(GreaterThan greaterThan)
         {
             Console.WriteLine("++++++ greaterThan");

             BinaryOperation newOp1 = new LessThan();
             newOp1.LeftOperand = greaterThan.LeftOperand;
             newOp1.RightOperand = greaterThan.RightOperand;

             BinaryOperation newOp2 = new LessThanOrEqual();
             newOp2.LeftOperand = greaterThan.LeftOperand;
             newOp2.RightOperand = greaterThan.RightOperand;

             BinaryOperation newOp3 = new GreaterThanOrEqual();
             newOp3.LeftOperand = greaterThan.LeftOperand;
             newOp3.RightOperand = greaterThan.RightOperand;

             BinaryOperation newOp4 = new Equality();
             newOp4.LeftOperand = greaterThan.LeftOperand;
             newOp4.RightOperand = greaterThan.RightOperand;

             BinaryOperation newOp5 = new NotEquality();
             newOp5.LeftOperand = greaterThan.LeftOperand;
             newOp5.RightOperand = greaterThan.RightOperand;


             list.Add(new Pair(greaterThan, newOp1));
             list.Add(new Pair(greaterThan, newOp2));
             list.Add(new Pair(greaterThan, newOp3));
             list.Add(new Pair(greaterThan, newOp4));
             list.Add(new Pair(greaterThan, newOp5));
             return this.Visit((BinaryOperation)greaterThan);
         }
        public override IExpression Visit(Equality equality)
        {
            Console.WriteLine("++++++ equality");

            INamespaceTypeReference typeRef = equality.LeftOperand.Type as INamespaceTypeReference;
            if (typeRef == null) return this.Visit((BinaryOperation)equality);
            if (typeRef.ToString().Equals(this.host.PlatformType.SystemFloat32.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemFloat64.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt16.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt32.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt64.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt8.ToString()))
            {
                BinaryOperation newOp1 = new LessThan();
                newOp1.LeftOperand = equality.LeftOperand;
                newOp1.RightOperand = equality.RightOperand;

                BinaryOperation newOp2 = new GreaterThan();
                newOp2.LeftOperand = equality.LeftOperand;
                newOp2.RightOperand = equality.RightOperand;

                BinaryOperation newOp3 = new GreaterThanOrEqual();
                newOp3.LeftOperand = equality.LeftOperand;
                newOp3.RightOperand = equality.RightOperand;

                BinaryOperation newOp4 = new LessThanOrEqual();
                newOp4.LeftOperand = equality.LeftOperand;
                newOp4.RightOperand = equality.RightOperand;

                list.Add(new Pair(equality, newOp1));
                list.Add(new Pair(equality, newOp2));
                list.Add(new Pair(equality, newOp3));
                list.Add(new Pair(equality, newOp4));
            }
            BinaryOperation newOp5 = new NotEquality();
            newOp5.LeftOperand = equality.LeftOperand;
            newOp5.RightOperand = equality.RightOperand;


            list.Add(new Pair(equality, newOp5));
            return this.Visit((BinaryOperation)equality);
        }

        public override IExpression Visit(NotEquality notEquality)
        {
            Console.WriteLine("++++++ notEquality");
            ITypeReference typeRef = notEquality.LeftOperand.Type as INamespaceTypeReference;
            if (typeRef == null) return this.Visit((BinaryOperation)notEquality);
            if (typeRef.ToString().Equals(this.host.PlatformType.SystemFloat32.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemFloat64.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt16.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt32.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt64.ToString()) || typeRef.ToString().Equals(this.host.PlatformType.SystemInt8.ToString()))
            {
                BinaryOperation newOp1 = new LessThan();
                newOp1.LeftOperand = notEquality.LeftOperand;
                newOp1.RightOperand = notEquality.RightOperand;

                BinaryOperation newOp2 = new GreaterThan();
                newOp2.LeftOperand = notEquality.LeftOperand;
                newOp2.RightOperand = notEquality.RightOperand;

                BinaryOperation newOp3 = new GreaterThanOrEqual();
                newOp3.LeftOperand = notEquality.LeftOperand;
                newOp3.RightOperand = notEquality.RightOperand;

                BinaryOperation newOp4 = new LessThanOrEqual();
                newOp4.LeftOperand = notEquality.LeftOperand;
                newOp4.RightOperand = notEquality.RightOperand;

                list.Add(new Pair(notEquality, newOp1));
                list.Add(new Pair(notEquality, newOp2));
                list.Add(new Pair(notEquality, newOp3));
                list.Add(new Pair(notEquality, newOp4));
            }
            BinaryOperation newOp5 = new Equality();
            newOp5.LeftOperand = notEquality.LeftOperand;
            newOp5.RightOperand = notEquality.RightOperand;

            list.Add(new Pair(notEquality, newOp5));
            return this.Visit((BinaryOperation)notEquality);
        }
        
        public override IExpression Visit(BinaryOperation operation)
        {
            // Console.WriteLine("++++++ condition_binaryoperation");
            CompileTimeConstant newOp1 = new CompileTimeConstant() { Value = true, Type = this.host.PlatformType.SystemBoolean };


            CompileTimeConstant newOp2 = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean };



            list.Add(new Pair(operation, newOp1));
            list.Add(new Pair(operation, newOp2));


            return base.Visit(operation);
        }
        
    }
}